<template name="yqking-avatar">
	<view>
		<image :src="avatarSrc" @click="fSelect" :style="[ imgStyle ]" class="my-avatar"></image>
		<canvas canvas-id="avatar-factory" class="my-canvas" :style="[ showStyle, cvsStyle ]" disable-scroll="false"></canvas>
		<canvas canvas-id="oper-canvas" class="oper-canvas" :style="[ showStyle, cvsStyle ]"
		disable-scroll="false" @touchstart="fStart" @touchmove="fMove" @touchend="fEnd"></canvas>
		<view class="oper-wrapper" :style="[ showStyle, tabStyle ]">
			<view class="oper">
				<view class="btn-wrapper">
					<view @click="fSelect"  hover-class="hover"><text>重选</text></view>
					<view @click="fPreview" hover-class="hover"><text>预览</text></view>
					<view @click="fUpload"  hover-class="hover"><text>上传</text></view>
				</view>
			</view>
		</view>
	</view>
</template>

<script>
	const tabHeight = 50;
	const moreHeight = 90;
	export default {
		data() {
			return {
				imgStyle: {},
				cvsStyle: {},
				tabStyle: {},
				selStyle: {},
				showStyle: {
					display: 'none'
				}
			};
		},
		props:{
			avatarSrc: '',
			avatarStyle: '',
			selWidth: '',
			selHeight: '',
		},
		created() {
			uni.onWindowResize(()=>{
				this.fWindowResize();
			})
			this.fWindowResize();
		},
		methods: {
			fWindowResize() {
				// #ifndef H5
				this.ctxCanvas = uni.createCanvasContext('avatar-factory', this);
				this.ctxCanvasOper = uni.createCanvasContext('oper-canvas', this);
				// #endif
				
				this.sysInfo = uni.getSystemInfoSync();
				// #ifdef H5
				this.sysInfo.windowHeight += moreHeight; //TODO 浏览器总比获取到的高度大 ?
				// #endif
				this.pixelRatio = this.sysInfo.windowWidth/750;
				this.cvsStyle.height = this.sysInfo.windowHeight - tabHeight + 'px';
				this.tabStyle.height = tabHeight + 'px';
				// console.log(JSON.stringify(this.sysInfo));
				
				let style = this.avatarStyle;
				if(style && style !== true && (style=style.trim()) ) {
					style = style.split(';');
					let obj = {};
					for( let v of style ) {
						v = v.trim().split(':');
						if(v[1].indexOf('upx') >= 0) {
							v[1] = parseFloat(v[1]) * this.pixelRatio + 'px';
						}
						obj[v[0].trim()] = v[1].trim();
					}
					this.imgStyle = obj;
				}
				
				style = this.selStyle;
				if( this.selWidth && this.selHeight ) {
					style.width  = this.selWidth.indexOf('upx')  >= 0 ? parseInt(this.selWidth)  * this.pixelRatio + 'px' : this.selWidth;
					style.height = this.selHeight.indexOf('upx') >= 0 ? parseInt(this.selHeight) * this.pixelRatio + 'px' : this.selHeight;
				}
				style.top = (this.sysInfo.windowHeight - parseInt(style.height) - tabHeight)/2 + 'px';
				style.left = (this.sysInfo.windowWidth - parseInt(style.width))/2 + 'px';
				this.selStyle = style;
			},
			fUpload() {
				if(this.fUploading)	return;
				this.fUploading = true; 
				setTimeout(()=>{ this.fUploading = false; }, 1000)
				
				let style = this.selStyle,
					x = parseInt(style.left) + 3,
					y = parseInt(style.top) + 3,
					width = parseInt(style.width) - 6,
					height = parseInt(style.height) - 6;
				// #ifdef H5
				x *= this.sysInfo.pixelRatio;
				y *= this.sysInfo.pixelRatio;
				width *= this.sysInfo.pixelRatio;
				height *= this.sysInfo.pixelRatio;
				// #endif
				
				uni.showLoading({
					mask: true
				});
				uni.canvasToTempFilePath({
					x: x,
					y: y,
					width: width,
					height: height,
					canvasId: 'avatar-factory',
					fileType: 'png',
					quality: 0.9,
					success: (r)=>{
						this.showStyle.display = 'none';
						
						r = r.tempFilePath;
						// #ifdef H5
						this.btop(r).then((r)=> {
							this.$emit("upload", r);
						})
						// #endif
						
						// #ifndef H5
						console.log(r)
						this.$emit("upload", r);
						// #endif
					},
					fail: (r) => {
						uni.showLoading({
							title: "error1",
							duration: 2000,
						})
					},
					complete: () => {
						uni.hideLoading();
					}
				}, this);
			},
			fDrawImage() {
				let tm_now = Date.now();
				if(tm_now - this.drawTm < 20) return;
				this.drawTm = tm_now;
				setTimeout(()=>{
					// #ifdef H5
					this.ctxCanvas.restore();
					this.ctxCanvas.save();
					// #endif
					
					this.ctxCanvas.fillRect(0, 0, this.sysInfo.windowWidth, this.sysInfo.windowHeight-tabHeight);
					this.ctxCanvas.translate(this.posWidth+this.useWidth/2, this.posHeight+this.useHeight/2);
					this.ctxCanvas.scale(this.scaleSize, this.scaleSize);
					this.ctxCanvas.rotate(this.rotateDeg * Math.PI/180);
					this.ctxCanvas.drawImage(this.imgPath, -this.useWidth/2, -this.useHeight/2, this.useWidth, this.useHeight);
					
					// #ifndef H5
					this.ctxCanvas.draw(false)
					// #endif
				}, 20);
			},
			fPreview() {
				if(this.fPreviewing) return;
				this.fPreviewing = true;
				setTimeout(()=>{ this.fPreviewing = false; }, 500)
				
				let style = this.selStyle,
					x = parseInt(style.left) + 3,
					y = parseInt(style.top) + 3,
					width = parseInt(style.width) - 6,
					height = parseInt(style.height) - 6;
				// #ifdef H5
				x *= this.sysInfo.pixelRatio;
				y *= this.sysInfo.pixelRatio;
				width *= this.sysInfo.pixelRatio;
				height *= this.sysInfo.pixelRatio;
				// #endif
				
				uni.showLoading({
					mask: true
				});
				uni.canvasToTempFilePath({
					x: x,
					y: y,
					width: width,
					height: height,
					canvasId: 'avatar-factory',
					fileType: 'png',
					quality: 0.9,
					success: (r)=>{
						r = r.tempFilePath;
						// #ifdef H5
						this.btop(r).then((r)=> {
							uni.previewImage({
								urls: [r]
							})
						})
						// #endif
						
						// #ifndef H5
						console.log(r)
						uni.previewImage({
							urls: [r]
						})
						// #endif
					},
					fail: (r) => {
						uni.showLoading({
							title: "error2",
							duration: 2000,
						})
					}, 
					complete: () => {
						uni.hideLoading();
					}
				}, this);
			},
			fSelect() {
				if(this.fSelecting) return;
				this.fSelecting = true;
				setTimeout(()=>{ this.fSelecting = false; }, 500)
				
				uni.chooseImage({
					count: 1,
					sizeType: ['original', 'compressed'],
					sourceType: ['album', 'camera'],
					success: (r)=>{
						let path = this.imgPath = r.tempFilePaths[0];
						uni.getImageInfo({
							src: path,
							success: r => {
								let allWidth = this.sysInfo.windowWidth,
									allHeight = this.sysInfo.windowHeight,
									imgWidth = r.width,
									imgHeight = r.height,
									imgRadio = imgWidth/imgHeight,
									useWidth = allWidth - 40,
									useHeight = allHeight - tabHeight - 80;
								
								if( imgRadio < 1 ) {
									if( imgHeight < useHeight ) {
										useWidth = imgWidth;
										useHeight = imgHeight;
									} else {
										useHeight = useHeight;
										useWidth = useHeight*imgRadio;
									}
								} else {
									if( imgWidth < useWidth ) {
										useWidth = imgWidth;
										useHeight = imgHeight;
									} else {
										useWidth = useWidth;
										useHeight = useWidth/imgRadio;
									}
								}
								this.scaleSize = 1;
								this.rotateDeg = 0;
								
								// #ifdef H5
								let cvs = document.getElementsByTagName('canvas');
								this.canvas = cvs[0];
								this.canvasOper = cvs[1]; 
								this.ctxCanvas = this.canvas.getContext("2d"); 
								this.ctxCanvasOper = this.canvasOper.getContext("2d"); 
								// #endif
									
								// #ifdef H5
								this.canvasOper.style.width = this.sysInfo.windowWidth + 'px';
								this.canvasOper.style.height = this.sysInfo.windowHeight - tabHeight + 'px';
								this.canvasOper.setAttribute("width", this.sysInfo.windowWidth * this.sysInfo.pixelRatio + 'px');
								this.canvasOper.setAttribute("height", this.sysInfo.windowHeight * this.sysInfo.pixelRatio + 'px');
								this.canvasOper.style.display = "fixed";
								this.canvasOper.style.top = "0";
								this.canvasOper.style.left = "0";
								this.ctxCanvasOper.lineWidth = 3;
								this.ctxCanvasOper.strokeStyle = 'grey';
								this.ctxCanvasOper.globalAlpha = 0.3;
								this.ctxCanvasOper.fillStyle = 'grey';
								// #endif
								
								// #ifndef H5
								this.ctxCanvasOper.setLineWidth(3);
								this.ctxCanvasOper.setStrokeStyle('grey');
								this.ctxCanvasOper.setGlobalAlpha(0.3);
								this.ctxCanvasOper.setFillStyle('grey');
								// #endif
								
								let style = this.selStyle,
									left = parseInt(style.left),
									top = parseInt(style.top),
									width = parseInt(style.width),
									height = parseInt(style.height); 
								this.ctxCanvasOper.strokeRect( left, top, width, height );
								this.ctxCanvasOper.fillRect(0, 0, this.sysInfo.windowWidth, top);
								this.ctxCanvasOper.fillRect(0, top, left, height);
								this.ctxCanvasOper.fillRect(0, top+height, this.sysInfo.windowWidth, this.sysInfo.windowHeight-height-top-tabHeight);
								this.ctxCanvasOper.fillRect(left+width, top,this.sysInfo.windowWidth-width-left, height);
								
								// #ifndef H5
								this.ctxCanvasOper.draw(false);
								// #endif
								
								this.posWidth = (allWidth-useWidth)/2;
								this.posHeight = (allHeight-useHeight-tabHeight)/2;
								this.useWidth = useWidth;
								this.useHeight = useHeight;
									
								// #ifdef H5
								this.imgPath = null;
								let img = new Image();
								img.src =  path;
								this.canvas.style.width = allWidth + 'px';
								this.canvas.style.height = allHeight - tabHeight + 'px';
								this.canvas.setAttribute("width", this.sysInfo.windowWidth * this.sysInfo.pixelRatio + 'px');
								this.canvas.setAttribute("height", this.sysInfo.windowHeight * this.sysInfo.pixelRatio + 'px');
								this.canvas.style.top = "0";
								this.canvas.style.left = "0";
								img.addEventListener("load", ()=>{
									this.imgPath = img;
									this.showStyle.display = "flex";
									this.ctxCanvas.fillStyle = 'black';
									this.fDrawImage();
								});
								// #endif
								
								// #ifndef H5
								this.showStyle.display = "flex";
								this.ctxCanvas.setFillStyle('black');
								this.fDrawImage();
								// #endif
							},
							fail() {
								uni.showLoading({
									title: "error3",
									duration: 2000,
								})
							}
						});
					}
				})
			},
			fStart(e) {
				let touches = e.touches,
				touch0 = touches[0],
				touch1 = touches[1];
				
				this.touch0 = touch0;
				this.touch1 = touch1;
				
				if( touch1 ) {
					let x = touch1.x - touch0.x,
						y = touch1.y - touch0.y;
					this.fgDistance = Math.sqrt(x * x + y * y);
				}
			},
			fMove(e) {
				let touches = e.touches,
					touch0 = touches[0],
					touch1 = touches[1];
					
				if( touch1 ) {
					let x = touch1.x - touch0.x,
						y = touch1.y - touch0.y,
						fgDistance = Math.sqrt(x * x + y * y),
						scaleSize = 0.005 * (fgDistance - this.fgDistance);
					if( this.scaleSize + scaleSize > 0.3 && this.scaleSize + scaleSize < 4 ) {
						this.scaleSize += scaleSize;
					} 
					this.fgDistance = fgDistance;
			
					if(touch1.x !== touch0.x) {
						x = (this.touch1.y - this.touch0.y)/(this.touch1.x - this.touch0.x);
						y = (touch1.y - touch0.y)/(touch1.x - touch0.x);
						this.rotateDeg += Math.atan((y-x)/(1+x*y)) * 180/Math.PI;
						this.touch0 = touch0;
						this.touch1 = touch1;
					}
					
					this.fDrawImage();
				} else {
					
					let x = touch0.x - this.touch0.x,
						y = touch0.y - this.touch0.y;
					if( Math.abs(x) < 100 ) this.posWidth  += x;
					if( Math.abs(y) < 100 ) this.posHeight += y;
					this.touch0 = touch0;
					
					this.fDrawImage();
				}
			},
			fEnd(e) {
				let touches = e.touches,
					touch0 = touches[0],
					touch1 = touches[1];
				if(touch0) {
					this.touch0 = touch0;
				} else {
					this.touch0 = null;
					this.touch1 = null;
				}
			},
			fCancel() {
				uni.showLoading({
					title: "error4",
					duration: 2000,
				})
			},
			fError() {
				uni.showLoading({
					title: "error5",
					duration: 2000,
				})
			},
			btop(base64) {
				return new Promise(function(resolve, reject) {
					base64 = base64.split(',')
					var type = base64[0].match(/:(.*?);/)[1]
					var str = atob(base64[1])
					var n = str.length
					var array = new Uint8Array(n)
					while (n--) {
						array[n] = str.charCodeAt(n)
					}
					return resolve((window.URL || window.webkitURL).createObjectURL(new Blob([array], { type: type })))
				});
			},
		},
		name: "yqking-avatar",
	}
</script>

<style>
	.my-canvas{
		position: fixed;
		background: #000000;
		top: 0;
		left: 0;
		z-index: 100000;
		width: 100%;
	}
	.my-avatar {
		width: 100upx;
		height: 100upx;
		border-radius: 50%;
	}
	.oper-canvas {
		position: fixed;
		top: 0;
		left: 0;
		z-index: 100001;
		width: 100%;
	}
	.oper-wrapper {
		position: fixed;
		background: #ffffff;
		width: 100%;
		left: 0;
		bottom: 0;
		z-index: 100009;
		flex-direction: row;
	}
	.oper {
		display: flex;
		flex-direction: column;
		justify-content: center;
		padding: 10upx 20upx;
		width: 100%;
		height: 100%;
		box-sizing: border-box;
		align-self: center;
	}
	.btn-wrapper {
		display: flex;
		flex-direction: row;
		flex: 3;
	}
	.btn-wrapper view {
		display: flex;
		flex-grow: 1;
		align-items: center;
		justify-content: center;
		font-size: 16px;
		color: #333;
		border: 1px solid #f1f1f1;
		border-radius: 6%;
		margin: 0 2px;
	}
	.hover {
		background: #f1f1f1;
		border-radius: 6%;
	}
	.clr-wrapper {
		display: flex;
		flex-direction: row;
		align-items: center;
		height: 30px;
		flex: 2;
	}
	.clr-wrapper view {
		margin-right: 10upx;
		font-size: 12px;
		color: #fff;
	}
</style>
